package com.itcast.rpc.core.server.handler;

import com.itcast.rpc.core.base.RpcRequest;
import com.itcast.rpc.core.base.RpcResponse;
import com.itcast.rpc.core.util.ClassUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;

/**
 * @program: bio_tcp
 * @description:
 * @author: zhanghz001
 * @create: 2021-02-23 11:07
 **/
public class ServerRpcHandler extends SimpleChannelInboundHandler<RpcRequest> {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(ServerRpcHandler.class);
    
    private static final HashMap<Class<?>, Object> OBJECT_MAP = new HashMap<>();
    
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext,
                                RpcRequest request) throws Exception {
        //创建响应对象
        String requestId = request.getRequestId();
        RpcResponse response = new RpcResponse();
        response.setRequestId(requestId);
        LOGGER.info("开始处理消息： requestId = " + request.getRequestId());
        
        //
        try {
            //创建对应的响应对象到map中
            String className = request.getClassName();
            Class<?> clazz = Class.forName(className);
            if (!OBJECT_MAP.containsKey(clazz)) {
                //获取接口的实现类,这里只取第一个实现类,忽略其他实现类
                List<Class> list = ClassUtil.getAllClassByInterface(clazz);
                for (Class c : list) {
                    //设置好存放对象的map
                    OBJECT_MAP.put(clazz, c.newInstance());
                    break;
                }
            }
            
            //反射出方法体
            String methodName = request.getMethodName();
            Method method = clazz.getMethod(methodName, request.getParameterTypes());
            //
            //设置访问权限
            method.setAccessible(true);
            
            //准备好执行对象
            Object obj = OBJECT_MAP.get(clazz);
            //方法执行的结果
            Object[] parameters = request.getParameters();
            Object result = method.invoke(obj, parameters);
            
            //
            response.setResult(result);
        } catch (Exception e) {
            LOGGER.error("处理失败... requestId = " + request.getRequestId(), e);
            //出错
            response.setErrorMsg("error");
            
        }
        
        //加入到发送中
        channelHandlerContext.writeAndFlush(response);
    }
}
